@file:OptIn(ExperimentalFoundationApi::class, ExperimentalTvMaterial3Api::class,
    ExperimentalComposeUiApi::class, ExperimentalTvMaterial3Api::class
)

package com.open.launcher.screen

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.foundation.PivotOffsets
import androidx.tv.foundation.lazy.list.TvLazyColumn
import androidx.tv.foundation.lazy.list.TvLazyRow
import androidx.tv.foundation.lazy.list.rememberTvLazyListState
import androidx.tv.material3.Border
import androidx.tv.material3.CardDefaults
import androidx.tv.material3.CardLayoutDefaults
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.FilterChip
import androidx.tv.material3.FilterChipDefaults
import androidx.tv.material3.ImmersiveList
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.ShapeDefaults
import androidx.tv.material3.StandardCardLayout
import androidx.tv.material3.Text
import coil.compose.AsyncImage
import com.open.launcher.R
import com.open.launcher.bean.MoviceData
import com.open.launcher.bean.getDatas
import com.open.launcher.bean.getDatas1
import com.open.launcher.bean.getDatas2
import com.open.launcher.bean.getDatasHead
import com.open.launcher.bean.getImmersDatas

@Composable
fun MoviceScreen() {
    val tvLazyListState = rememberTvLazyListState()
    TvLazyColumn(
        state = tvLazyListState,
        modifier = Modifier
            .fillMaxSize()
    ) {
        item {
            MovicesImmersList(getImmersDatas())
        }
        item {
            MoviesLazyRow("热门推荐", getDatas())
        }
        item {
            MovicesColumnItem()
        }
        item {
            MoviesLazyRow("豆瓣高分", getDatasHead(), contentPadding = 30.dp, itemWidth = 412.dp, itemHeight = 200.dp)
            MoviesLazyRow("", getDatas1(), isNoTitle = true)
        }
        item {
            MoviesLazyRow("预热抢先看", getDatas2())
        }
        item {
            Spacer(
                modifier = Modifier.padding(
                    bottom =
                    LocalConfiguration.current.screenWidthDp.dp.times(0.19f)
                )
            )
        }
    }
}

@Composable
fun MovicesImmersList(datas:List<MoviceData>) {
    var isListFocused by remember { mutableStateOf(false) }
    var currentItemIndex by remember { mutableStateOf(0) }
    var currentYCoord: Float? by remember { mutableStateOf(null) }

    ImmersiveList(
        modifier = Modifier.onGloballyPositioned { currentYCoord = it.positionInWindow().y },
        background = { index, listHasFocus ->
            isListFocused = listHasFocus
            val height = 750.dp
            AnimatedVisibility(
//                visible = isListFocused,
                visible = true,
                enter = fadeIn() + expandVertically(),
                exit = fadeOut() + shrinkVertically(),
                modifier = Modifier
                    .height(height)
                    .gradientOverlay(colorResource(R.color.surface))
            ) {
                val movie = remember(datas, currentItemIndex) {
                    datas[currentItemIndex]
                }
                if (movie.bgUrl.isEmpty()) {
                    movie.bgUrl = movie.url
                }
                Crossfade(targetState = movie.bgUrl, label = "CrossfadeUriTest") { posterUri ->
                    AsyncImage(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(height),
                        model = posterUri,
                        contentDescription = null,
                        contentScale = ContentScale.Crop
                    )
                }
            }
        },
        list = {
            Column(
                modifier = Modifier.focusGroup()
            ) {
//                    if (isListFocused) {
                AnimatedVisibility(
                    visible = isListFocused,
                    enter = slideInHorizontally(initialOffsetX ={it}) + fadeIn(),
                    exit = slideOutHorizontally(targetOffsetX = {it}) + fadeOut()
                ) {
                    val movie = remember(datas, currentItemIndex) {
                        datas[currentItemIndex]
                    }
                    Column(
                        modifier = Modifier.padding(start = 90.dp, bottom = 40.dp)
                    ) {
                        Text(text = movie.title, style = MaterialTheme.typography.displaySmall.copy(fontSize = 40.sp),
                            color = Color.White)
                        Spacer(modifier = Modifier.padding(top = 8.dp))
                        Text(
                            modifier = Modifier.fillMaxWidth(0.5f),
                            text = movie.detail,
                            style = MaterialTheme.typography.bodyLarge.copy(fontSize = 23.sp),
                            color = Color.White.copy(alpha = 0.75f),
                            fontWeight = FontWeight.Light
                        )
                    }
                }
                //
                TvLazyRow(
                    modifier = Modifier
                        .focusRestorer()
                        .height(200.dp),
                    contentPadding = PaddingValues(16.dp),
                    horizontalArrangement = Arrangement.spacedBy(20.dp)
                ) {
                    item {
                        Spacer(modifier = Modifier.width(50.dp))
                    }
                    datas.forEachIndexed { index, moviceData ->
                        item {
                            MoviesRowItem(index=index, width = 300.dp, height = 200.dp, data = moviceData) {
                                currentItemIndex = it
                            }
                        }
                    }
                }
            }
        })
}

@Composable
fun MoviesLazyRow(
    title:String="测试",
    datas:List<MoviceData>,
    isNoTitle:Boolean=false,
    contentPadding:Dp=30.dp,
    itemWidth:Dp=223.dp,
    itemHeight:Dp=310.dp
) {
    Column(
        modifier = Modifier.focusGroup(),
    ) {
        if (!isNoTitle) {
            Text(
                text = title,
                style = MaterialTheme.typography.headlineLarge.copy(
                    fontWeight = FontWeight.Bold,
                    fontSize = 36.sp
                ),
                modifier = Modifier
                    .alpha(1f)
                    .padding(start = 90.dp)
                    .padding(vertical = 20.dp),
                color = Color.White
            )
        }
        Box(
            modifier = Modifier.fillMaxWidth(),
            contentAlignment = Alignment.Center
        ) {
            TvLazyRow(
                pivotOffsets = PivotOffsets(parentFraction = 0.42f),
                contentPadding = PaddingValues(contentPadding),
                horizontalArrangement = Arrangement.spacedBy(30.dp)
            ) {
                items(datas.size) {
                    MoviesRowItem(it, data=datas[it], width=itemWidth, height = itemHeight)
                }
            }
        }
    }
}

@Composable
fun MoviesRowItem(index: Int=0, width:Dp=223.dp, height:Dp=310.dp, data: MoviceData, focusedItemIndex: (index: Int) -> Unit = {}) {
    var isItemFocused by remember { mutableStateOf(false) }
    StandardCardLayout(
        modifier = Modifier
            .width(
                width
            )
            .onFocusChanged {
                isItemFocused = it.isFocused
                if (isItemFocused) {
                    focusedItemIndex(index)
                }
            }
            .focusProperties {

            },
        imageCard = {
            CardLayoutDefaults.ImageCard(
                onClick = {},
                shape = CardDefaults.shape(ShapeDefaults.ExtraSmall),
                border = CardDefaults.border(
                    focusedBorder = Border(
                        border = BorderStroke(
                            width = 3.dp,
                            color = Color.White
                        ),
                        shape = ShapeDefaults.ExtraSmall
                    )
                ),
                scale = CardDefaults.scale(focusedScale = 1.0f),
                interactionSource = it
            ) {
                AsyncImage(
                    modifier= Modifier
                        .fillMaxWidth()
                        .height(height),
                    model = data.url,
                    contentScale = ContentScale.Crop,
                    contentDescription ="${data.title}",
                    error = painterResource(id = R.drawable.movice_pic1)
                )
            }
        },
        title = {
            if (data.title.isNotEmpty()) {
                val movieNameAlpha by animateFloatAsState(
                    targetValue = if (isItemFocused) 1f else 0f,
                    label = "",
                )
                Text(
                    text = data.title,
                    color = Color.White,
                    style = MaterialTheme.typography.bodyMedium.copy(
                        fontWeight = FontWeight.SemiBold, fontSize = 20.sp
                    ),
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                        .alpha(movieNameAlpha)
                        .fillMaxWidth()
                        .padding(top = 4.dp)
                        .basicMarquee()/*跑马灯*/,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
            }
        })
}

val columnDatas = listOf("票房榜", "喜剧", "战争", "动画", "科幻", "热血动作", "全部")


@Composable
fun MovicesColumnItem() {
    TvLazyRow(modifier = Modifier.padding(start = 90.dp, bottom = 30.dp)) {
        columnDatas.forEachIndexed { index,text->
            item {
                FilterChip(
                    modifier = Modifier
                        .padding(end = 20.dp)
                        .width(232.dp)
                        .height(100.dp),
                    shape = FilterChipDefaults.shape(shape = ShapeDefaults.ExtraSmall),
                    border = FilterChipDefaults.border(
                        border = Border(
                            border = BorderStroke(
                                width = 2.dp, color = MaterialTheme.colorScheme.border.copy(alpha = 0.5f)
                            ), shape = ShapeDefaults.ExtraSmall
                        ),
                        focusedBorder = Border(
                            border = BorderStroke(
                                width = 2.dp,
                                color = Color.White,
                            ), shape = ShapeDefaults.ExtraSmall
                        ),
                    ),
                    colors = FilterChipDefaults.colors(
                        focusedContainerColor = Color.Transparent,
                        selectedContainerColor = ChipColor,
                        focusedSelectedContainerColor = ChipColor,
                        focusedContentColor = Color.White,
                        focusedSelectedContentColor = ChipContentColor
                    ),
                    scale = FilterChipDefaults.scale(focusedScale = 1f),
                    selected = false, onClick = { }) {
                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.Center
                    ) {
                        Text(
                            "$text",
                            style = MaterialTheme.typography.titleMedium.copy(
                                color = Color.White,
                                fontSize = 32.sp
                            )
                        )
                    }
                }
            }
        }
    }
}

private val ChipColor @Composable get() = Color.White.copy(alpha = 0.1f)
private val ChipContentColor @Composable get() = MaterialTheme.colorScheme.inverseSurface

// 沉浸式列表增加蒙层
fun Modifier.gradientOverlay(gradientColor: Color) = this then drawWithCache {
    val horizontalGradient = Brush.horizontalGradient(
        colors = listOf(
            gradientColor,
            Color.Transparent
        ),
        startX = size.width.times(0.2f),
        endX = size.width.times(0.7f)
    )
    val verticalGradient = Brush.verticalGradient(
        colors = listOf(
            Color.Transparent,
            gradientColor
        ),
        endY = size.width.times(0.3f)
    )
    val linearGradient = Brush.linearGradient(
        colors = listOf(
            gradientColor,
            Color.Transparent
        ),
        start = Offset(
            size.width.times(0.2f),
            size.height.times(0.5f)
        ),
        end = Offset(
            size.width.times(0.9f),
            0f
        )
    )

    onDrawWithContent {
        drawContent()
        drawRect(horizontalGradient)
        drawRect(verticalGradient)
        drawRect(linearGradient)
    }
}

